#ifndef __LUA_VM__
#define __LUA_VM__

#include "base.h"
#include "message.h"
#include "stream_reader.h"
#include "stream_writer.h"

#ifdef __cplusplus
extern "C" {
#endif
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#ifdef __cplusplus
}
#endif

class LuaVm {
public:
	LuaVm(const std::string& entry = "") : L(NULL), entry_(entry), errHandle_(0){}

	virtual ~LuaVm();

	bool load();

	bool call(const char* f, StreamReader* params = NULL, StreamWriter* rets = NULL);
	bool callEx(const char* f, StreamReader* params = NULL, StreamWriter* rets = NULL);
	bool callModule(const char* entryfunc, const char* modname, uint64 handle, const char* f, StreamReader* params = NULL, StreamWriter* rets = NULL);
	bool callModuleEx(const char* entryfunc, const char* modname, uint64 handle, const char* f, StreamReader* params = NULL, StreamWriter* rets = NULL);

	void setEntry(const std::string& entry) {
		entry_ = entry;
	}

	bool close();

	virtual void loadGameLibs() {};

	static bool readRet(lua_State* L, int32 index, StreamWriter& rets);
	static bool readRetEx(lua_State* L, int32 index, StreamWriter& rets);
private:
	int32 setParams(StreamReader& params);
	void setParam(StreamReader& params);
	typedef bool (*ReadRetFunc)(lua_State* L, int32, StreamWriter&);
	bool _call(const char* entryfunc, const char* modname, uint64 handle, const char* f, StreamReader* params, StreamWriter* rets, ReadRetFunc readf);
protected:
	lua_State* L;
	std::string entry_;
	int32 errHandle_;
};

#endif
